

#include <cstdint>
#include <cstdio>
#include "./../io_poll.h"
#include <gtest/gtest.h>
#include <sys/epoll.h>
#include <sys/poll.h>
#include <sys/socket.h>
#include <unistd.h>
#include <vector>
#include "test_util.h"
#include "./../../log_module/log_module_define.h"

TEST(IoPoll, ClientSocket)
{
    IoPoll poll;
    int client_socket = CreateClientSocket();
    {
        struct pollfd event;
        event.events = POLLIN | POLLOUT | POLLERR | POLLRDHUP;
        event.revents = 0;
        event.fd = client_socket;

        poll.AddPollEvent(event);
    }
    while(true)
    {
        std::vector<struct pollfd> vec;
        int size = poll.PollWait(vec, -1);
        if (size > 0)
        {
            for (auto & data : vec)
            {
                printf("client socket  : %d.\n", data.fd);
                printf("event & POLLIN : %d.\n", data.revents & POLLIN);
                printf("event & POLLOUT : %d.\n", data.revents & POLLOUT);
                printf("event & POLLERR : %d.\n", data.revents & POLLERR);
                printf("event & POLLRDHUP : %d.\n\n", data.revents & POLLRDHUP);

                if (data.revents & POLLOUT)
                {
                    struct pollfd revents;
                    revents.events = POLLIN | POLLERR | POLLRDHUP;
                    revents.fd     = data.fd;
                    poll.ModPollEvent(revents);
                }
                else if (data.revents & POLLIN)
                {
                    if (data.revents & POLLRDHUP)
                    {                        
                        poll.DelPollEvent(data);
                        close(client_socket);
                        client_socket = 0;
                        break;
                    }
                    else
                    {
                        struct pollfd revents;
                        revents.events = POLLIN | POLLRDHUP | POLLERR;
                        revents.fd     = data.fd;
                        poll.ModPollEvent(revents);
                    }
                }
            }
        }
        if (client_socket == 0)
        {
            break;
        }

    }
}

TEST(IoPoll, ServerSocket)
{
    IoPoll poll;
    int server_socket = CreateServerSocket();
    printf("server socket (%d).\n", server_socket);
    {
        struct pollfd event;
        event.events = POLLIN |  POLLRDHUP | POLLERR;
        event.fd     = server_socket;
        poll.AddPollEvent(event);
    }
    while (true)
    {
        std::vector<struct pollfd> vec;
        int size = poll.PollWait(vec, -1);
        if (size > 0)
        {
            for (auto & data : vec)
            {
                printf("event trigger fd : %d.\n", data.fd);
                printf("event & POLLIN : %d.\n", data.revents & POLLIN);
                printf("event & POLLOUT : %d.\n", data.revents & POLLOUT);
                printf("event & POLLERR : %d.\n", data.revents & POLLERR);
                printf("event & POLLRDHUP : %d.\n\n", data.revents & POLLRDHUP);
                
                if (data.fd == server_socket && data.revents & POLLIN)
                {
                    int new_client_socket = accept(data.fd, nullptr, nullptr);
                    if (new_client_socket > 0)
                    {
                        printf("new client socket (%d).\n", new_client_socket);
                        struct pollfd event;
                        event.events = POLLIN | POLLOUT | POLLRDHUP | POLLERR;
                        event.fd     = new_client_socket;
                        poll.AddPollEvent(event);
                    }
                }
                if (data.fd == server_socket && data.revents & POLLOUT)
                { 
                    data.events = POLLIN | POLLERR | POLLRDHUP;
                    poll.ModPollEvent(data);
                }
                else if (data.fd == server_socket)
                {

                }
                else
                {
                    if (data.revents & POLLIN)
                    {
                        if (data.revents & POLLRDHUP)
                        {
                            poll.DelPollEvent(data);
                            close(data.fd);
                        }
                        else 
                        {
                            uint8_t read_array[100] = {0};
                            ssize_t read_size = read(data.fd, read_array, sizeof(read_array));
                            if (read_size == 0)
                            {
                                poll.DelPollEvent(data);
                                close(data.fd);
                            }
                            else
                            {
                                printf("read data size : %ld.\n", read_size);
                            }
                        }
                    }
                    else
                    {
                        data.events = POLLIN | POLLRDHUP | POLLERR;
                        poll.ModPollEvent(data);
                    }
                
                }
            }
        }

    }

}


int main(int argc, char * argv[])
{
    testing::InitGoogleTest(&argc, argv);
    
    LogModuleConfig config;
    config.m_file_name = argv[0];
    LogModule::Instance()->InitModule(config);
    return RUN_ALL_TESTS();
}








